﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

using Newtonsoft.Json.Linq;

using Newtonsoft.Json.Serialization;

using Newtonsoft.Json;

namespace System.Net.Http
{
    public class JsonContent : HttpContent
    {
        private readonly Encoding defaultEncoding = Encoding.UTF8;

        private readonly JToken value;

        private byte[] _bytes;

        public static JsonSerializer DefaultJsonSerializer = new JsonSerializer()
        {
            DateFormatString = "yyyy-MM-dd HH:mm:ss",
            NullValueHandling = NullValueHandling.Ignore,
            Formatting = Formatting.None,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };


        public JsonContent(object content) : this(content, DefaultJsonSerializer)
        {

        }

        public JsonContent(object content, JsonSerializer jsonSerializer) : base()
        {
            if (content is JToken)
            {
                this.value = content as JToken;
            }
            else if (content is String str)
            {
                this.value = JToken.Parse(str);
            }
            else
            {
                this.value = JToken.FromObject(content, jsonSerializer);
            }

            base.Headers.ContentType =  MediaTypeHeaderValue.Parse("application/json;charset=UTF-8");
        }

        public JToken GetJToken()
        {
            return this.value;
        }

        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            var bytes = GetContentByteArray();
            return stream.WriteAsync(bytes, 0, bytes.Length);
        }


        private byte[] GetContentByteArray()
        {
            if (_bytes == null)
                _bytes = defaultEncoding.GetBytes(this.value.ToString(Formatting.None));
            return _bytes;
        }


        protected override bool TryComputeLength(out long length)
        {
            var bytes = GetContentByteArray();
            length = bytes.Length;
            return true;
        }
    }
}
